package com.test.spring.aop.xml;

import org.aspectj.lang.JoinPoint;

import java.util.Arrays;
import java.util.List;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/9/27 18:16
 * <p>
 * 把这个类设置为一个切面：
 * 1.需要把该类放入ioc容器中
 * 2.再声明为一个切面
 * <p>
 * 可以使用@Order指定切面的优先级，值越小，优先级越高
 */
public class LoggingAspect {
    //声明该方法是一个前置通知：在目标方法开始之前执行
    public void beforeMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("The method " + methodName + " begins with" + args);
    }

    //后置通知：在目标方法执行后（无论该方法是否发生异常），执行的通知
    //在后置通知中还不能访问目标方法执行的结果
    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends");
    }

    // 方法正常结束后执行的代码
    // 返回通知是可以访问到方法的返回值的
    public void afterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " ends with " + result);
    }

    //在目标方法出现异常时会执行的代码
    //可以访问到异常对象，且可以指定在出现特定异常的时候再执行通知代码
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("The method " + methodName + " occurs with exception " + ex);
    }

    /**
     * 环绕通知需要携带ProceedingJoinPoint类型的参数
     * 环绕通知类似于动态代理的全过程：ProceedingJoinPoint类型的参数可以决定是否执行目标方法
     * 环绕通知必须有返回值，返回值即为目标方法的返回值
     *
     * @param joinPoint
     */
    /*@Around("execution(* com.test.spring.aop.*.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) {
        System.out.println("around method");

        Object result = null;
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());

        //执行目标方法
        try {
            //前置通知
            System.out.println("The method " + methodName + " begins with result " + args);
            result = joinPoint.proceed();
            System.out.println("The method " + methodName + " ends with " + result);
            //返回通知
        } catch (Throwable throwable) {
            //异常通知
            System.out.println("The method " + methodName + " occurs with exception " + throwable);
            throw new RuntimeException(throwable);
        }

        //后置通知
        System.out.println("The method " + methodName + " ends");

        return 100;
    }*/
}
